﻿using System;

using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Common;
using System.IO;


namespace Tools
{
    public class NetToolKit : OrdinarySingleton<NetToolKit>, IDestroy
    {




        #region 字节流与结构体互相转换
        /// <summary>
        ///结构体转字节数组
        /// </summary>
        /// <returns>The to bytes.</returns>
        /// <param name="structObj">Struct object.</param>

        public byte[] StructToBytes(object structObj)
        {

            int size = ObjectSize(structObj.GetType());
            IntPtr buffer = Marshal.AllocHGlobal(size);
            try
            {
                Marshal.StructureToPtr(structObj, buffer, false);
                byte[] bytes = new byte[size];
                Marshal.Copy(buffer, bytes, 0, size);
                return bytes;
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
        /// <summary>
        /// 字节数组转结构体
        /// </summary>
        /// <returns>The to struct.</returns>
        /// <param name="bytes">Bytes.</param>
        /// <param name="strcutType">Strcut type.</param>
        public object BytesToStruct(byte[] bytes, Type strcutType)
        {

            int size = ObjectSize(strcutType);
            IntPtr buffer = Marshal.AllocHGlobal(size);
            try
            {
                Marshal.Copy(bytes, 0, buffer, size);
                return Marshal.PtrToStructure(buffer, strcutType);
            }
            catch(Exception e)
            {
                string msg = string.Format("bytes Length:{0},strcutType:{1} Struct Size:{2}", bytes.Length,strcutType.ToString(), size);
                return null;
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }

        }

        /// <summary>
        /// 字节数组转结构体
        /// </summary>
        /// <returns>The to struct.</returns>
        /// <param name="bytes">Bytes.</param>
        /// <param name="strcutType">Strcut type.</param>
        public object BytesToStruct(byte[] bytes,int start, Type strcutType)
        {

            int size = ObjectSize(strcutType);
            IntPtr buffer = Marshal.AllocHGlobal(size);
            try
            {
                Marshal.Copy(bytes, start, buffer, size);
                return Marshal.PtrToStructure(buffer, strcutType);
            }
            catch (Exception e)
            {
                string msg = string.Format("bytes Length:{0},strcutType:{1} Struct Size:{2}", bytes.Length, strcutType.ToString(), size);
                UnityEngine.Debug.LogError(msg);
                UnityEngine.Debug.LogError(e.Message);
                return null;
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }

        }

        public List<object> BytesToStructArray(byte[] bytes, Type structType)
        {
            List<object> structs = new List<object>();

            int structszie = ObjectSize(structType);
            int len = bytes.Length;
            if (len % structszie != 0)
            {
                string msg = string.Format("[NetToolKit][BytesToStructArray]byte Array length:{0},struct szie:{1},struct Type:{2}", len, structszie, structType);
                UnityEngine.Debug.LogError(msg);
                return null;
            }
            int index = 0;
            while (index + structszie <= len)
            {
                byte[] d = new byte[structszie];
                System.Array.Copy(bytes, index, d, 0, structszie);
                object _struct = BytesToStruct(d, structType);
                structs.Add(_struct);
                index += structszie;
            }
            return structs;
        }
        /// <summary>
        /// 结构体大小判断，true，符合预期
        /// </summary>
        /// <param name="DataLength"></param>
        /// <param name="strcutType"></param>
        /// <returns></returns>
        public bool AssertSize(int DataLength, Type strcutType)
        {
            int size = ObjectSize(strcutType);
            if (size != DataLength)
            {
                string msg = string.Format("DataLength:{0}, struct size:{1},struct type:{2}", DataLength, size, strcutType.ToString());
             //   Logger.Log(msg, "NetToolKit", "AssertSize");
                return false;
            }

            return true;
        }


        /// <summary>
        /// 获得数据包大小
        /// </summary>
        /// <param name="objecttype">结构体类型</param>
        /// <returns></returns>
        public int ObjectSize(Type objecttype)
        {

            return Marshal.SizeOf(objecttype);
        }

        #endregion


        public byte[] SbyteToByte(sbyte[] sd)
        {

            byte[] dest = Array.ConvertAll(sd, (a) => (byte)a);
            return dest;
        }

        public sbyte[] byteToSbyte(byte[] mb)
        {

            sbyte[] data = new sbyte[mb.Length];

            for (int i = 0; i < mb.Length; i++)
            {
                byte b = mb[i];
                data[i] = unchecked((sbyte)b);
            }
            return data;
        }

        public string SbyteArrayToString(sbyte[] data)
        {
            sbyte[] sdata = SbyteTrim(data);
            byte[] bytes = SbyteToByte(sdata);

            return ByteArrayToString(bytes);
        }

        public string ByteArrayToString(byte[] data)
        {
            string str = Encoding.GetEncoding(936).GetString(data);

            return str;
        }

        public string SbyteArrayToString(sbyte[] data, int encode)
        {
            sbyte[] sdata = SbyteTrim(data);
            byte[] bytes = SbyteToByte(sdata);
            Encoding e = Encoding.GetEncoding(encode);
            string ss = e.GetString(bytes);
            return ss;
        }

        public sbyte[] SbyteTrim(sbyte[] data)
        {
            int index = 0;

            for (; index < data.Length; index++)
            {
                sbyte sb = data[index];

                if (sb == 0)
                {
                    break;
                }

            }

            sbyte[] sdata = new sbyte[index];

            System.Array.Copy(data, sdata, index);

            return sdata;
        }

        public sbyte[] StringToSbyteArray(string str)
        {

            //byte[] byteArray = Encoding.Default.GetBytes(str);
            byte[] byteArray = Encoding.GetEncoding(936).GetBytes(str);
            sbyte[] data = byteToSbyte(byteArray);
            return data;
        }


        public string Print<T>(T[] data, int Start, int end)
        {

            StringBuilder sb = new StringBuilder("[");
            for (int i = Start; i < end; i++)
            {
                T b = data[i];
                if (b == null)
                {
                    sb.Append("null").Append(",");
                }
                else
                {
                    sb.Append(b.ToString()).Append(",");
                }
            }
            sb.Append("]");

            return sb.ToString();

        }

        public string Print<T>(T[] data)
        {

            return Print<T>(data, 0, data.Length);
        }

        public string Print<T>(List<T> data)
        {
            return Print<T>(data.ToArray());
        }


        public  string Print<T>(T[,] data)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("{");
            int k1 = data.GetLength(0);
            int k2 = data.GetLength(1);

            for (int i = 0; i < k1; i++)
            {
                sb.Append("[");
                for (int j = 0; j < k2; j++)
                {
                    T item = data[i, j];
                    sb.Append(item.ToString());
                    sb.Append(",");
                }
                sb.Append("],");
            }
            sb.Append("},");

            return sb.ToString();
        }

        /// <summary>
        /// 将字节数组转换为 int
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public List<int> BytesToIntArray(byte[] data)
        {
            int len = data.Length;

            if (len % 4 != 0)
            {
                string msg = string.Format("data.Length %4 != 0=>data.Length:{0}", len);
             //   Logger.ErrorInfo(msg, "NetToolKit", "BytesToIntArray");
            }

            List<int> ints = new List<int>();

            int index = 0;

            while (index + 4 < len)
            {
                byte[] temp = new byte[4];
                int k = BytesToInt(temp);

                ints.Add(k);
                index += 4;
            }

            return ints;

        }


        public int BytesToInt(byte[] data)
        {

            if (data.Length != 4)
            {
                string msg = string.Format("data.Length !=4-->data.Length:{0}", data.Length);
            //    Logger.ErrorInfo(msg, "NetToolKit", "BytesToIntArray");
                return -1;
            }

            // If the system architecture is little-endian (that is, little end first),
            // reverse the byte array.
            if (BitConverter.IsLittleEndian)
                Array.Reverse(data);

            int i = BitConverter.ToInt32(data, 0);

            return i;

        }


        public bool IsInteger(string strIn)
        {
            bool bolResult = true;
            if (string.IsNullOrEmpty(strIn))
            {
                bolResult = false;
            }
            else
            {
                foreach (char Char in strIn)
                {
                    if (char.IsNumber(Char))
                        continue;
                    else
                    {
                        bolResult = false;
                        break;
                    }
                }
            }
            return bolResult;
        }



        //public void SetGoldStr(long goldNum, UILabel label_goldNum)
        //{

        //    string GoldStr = goldNum.ToString();
        //    if (goldNum > 100000000)
        //    {
        //        double k = goldNum * 1.0d / 100000000;
        //        //   k = Math.Round(k, 1, MidpointRounding.AwayFromZero);
        //        GoldStr = k.ToString("f2") + "亿";

        //    }
        //    else if (goldNum > 10000000)
        //    {
        //        double k = goldNum * 1.0d / 10000000;
        //        //   k = Math.Round(k, 1, MidpointRounding.AwayFromZero);
        //        GoldStr = k.ToString("f2") + "千万";

        //    }
        //    else if (goldNum > 10000)
        //    {
        //        double k = goldNum * 1.0d / 10000;
        //        //  k = Math.Round(k, 1, MidpointRounding.AwayFromZero);
        //        GoldStr = k.ToString("f2") + "万";

        //    }
        //    label_goldNum.text = GoldStr;
        //    label_goldNum.MakePixelPerfect();

        //    string msg = string.Format("goldNum:{0},goldLable:{1}", goldNum, GoldStr);

        //     Logger.DebugInfo(msg, "GameToolKit", "SetGoldStr");

        //}
        /// <summary>
        /// 清空数组
        /// </summary>
        public void memset<T>(T[] buff)
        {
            Array.Clear(buff, 0, buff.Length);
        }
        /// <summary>
        /// 清空数组
        /// </summary>
        public void memset<T>(T[,] buff)
        {
            Array.Clear(buff, 0, buff.Length);
        }
        /// <summary>
        /// 拷贝数组
        /// </summary>
        public void memcpy<T>(T[] targetBuff, T[] sourceBuff)
        {
            if (targetBuff.Length >= sourceBuff.Length)
            {
                Array.Copy(sourceBuff, targetBuff, sourceBuff.Length);
            }

        }

        /// <summary>
        /// 拷贝数组
        /// </summary>
        public void memcpy<T>(T[,] targetBuff, T[,] sourceBuff)
        {
            if (targetBuff.Length == sourceBuff.Length)
            {
                Array.Copy(sourceBuff, targetBuff, sourceBuff.Length);
            }
            else
            {
                string msg = string.Format("targetBuff.Length:{0} == sourceBuff.Length:{1}", targetBuff.Length, sourceBuff.Length);
                UnityEngine.Debug.LogError(msg);
            }

        }


        /// <summary>
        /// 将长字符串分割成几段，遇到@分隔
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="sublen">每段字符串长度</param>
        /// <returns></returns>
        public string SliptString(string msg)
        {
            int len = msg.Length;
            StringBuilder sb = new StringBuilder();
            char[] separator = { '@' };
            string[] arr = msg.Split(separator);
            for (int i = 0; i < arr.Length; i++)
            {
                sb.AppendLine(arr[i]);
            }

            return sb.ToString();
        }



        public void CreateFile(string path, string name, byte[] info, int length)
        {
            //文件流信息
            //StreamWriter sw;
            Stream sw;
            FileInfo t = new FileInfo(path + "//" + name);
            if (!t.Exists)
            {
                //如果此文件不存在则创建
                sw = t.Create();
            }
            else
            {
                //如果此文件存在则打开
                //sw = t.Append();
                return;
            }
            //以行的形式写入信息
            //sw.WriteLine(info);
            sw.Write(info, 0, length);

            //关闭流
            sw.Close();
            //销毁流
            sw.Dispose();
        }

        public void DestroySelf()
        {

        }
    }
}
